#!/usr/bin/python
# -*- coding: utf-8 -*-

import Ice
import os

try:
    HOME = os.environ['FIPA']
except KeyError:
    print 'FIPA environment variable is not currently defined.'
    sys.exit(0)

SLICE = os.path.join(HOME, 'slice')
FILE1 = os.path.join(SLICE, 'FIPA.ice')
Ice.loadSlice('--all -I/usr/share/slice', ['-I' + SLICE, FILE1])

import FIPA, PropertyService

class PropertySetI (PropertyService.PropertySet):

    def __init__ (self, allowedProperties, initialProperties):
        # TODO
        self.__allowedProperties = allowedProperties
        self.__properties = {}
        if initialProperties:
            self.defineProperties(initialProperties)

    def defineProperty (self, theName, theValue, curr = None):
        if self.__properties.has_key(theName):
            if type(self.__properties.get(theName)) != type(theValue):
                raise PropertyService.UnsupportedTypeCode

        self.__properties[theName] = theValue

    def defineProperties (self, nproperties, curr = None):
        exceptions = []

        for p in nproperties.items():
            try:
                self.defineProperty(p[0], p[1])
            except PropertyService.UnsupportedTypeCode:
                ex = PropertyService.PropertyException(PropertyService.ExceptionReason.rUnsupportedTypeCode, p[0])
                exceptions.append(ex)

        if len(exceptions) > 0:
            raise PropertyService.MultipleExceptions(exceptions)

    def getNumberOfProperties (self, curr = None):
        return len(self.__properties)

    def getAllPropertyNames (self, howMany, curr):
        if len(self.__properties) > howMany:
            propertyNames = self.__properties.keys()[(howMany):len(self.__properties)]
            prx = curr.adapter.addWithUUID(PropertyNamesIteratorI(propertyNames))
            it = PropertyService.PropertyNamesIteratorPrx.uncheckedCast(prx)
            return (self.__properties.keys()[0:howMany], it)
        else:
            return (self.__properties.keys(), None)

    def getPropertyValue (self, theName, curr = None):
        try:
            return self.__properties[theName]
        except KeyError:
            raise PropertyService.PropertyNotFound

    def getProperties (self, theNames, curr = None):
        properties = {}

        for n in theNames:
            if self.__properties.has_key(n):
                properties[n] = self.__properties[n]

        if len(properties) > 0:
            return True, properties
        else:
            return False, None

    def getAllProperties (self, howMany, curr):
        if len(self.__properties) > howMany:
            # TODO
            #properties = self.__properties.copy()
            #prx = curr.adapter.addWithUUID(PropertiesIteratorI(properties))
            #it = PropertyService.PropertiesIteratorPrx.uncheckedCast(prx)
            #return (self.__properties.values()[0:howMany], it)
            return (self.__properties.values(), None)
        else:
            return (self.__properties, None)

    def deleteProperty (self, theName, curr = None):
        try:
            del self.__properties[theName]
        except KeyError:
            raise PropertyService.PropertyNotFound

    def deleteProperties (self, theNames, curr = None):
        exceptions = []

        for n in theNames:
            try:
                self.deleteProperty(n)
            except PropertyService.PropertyNotFound:
                ex = PropertyService.PropertyException(PropertyService.ExceptionReason.rInvalidPropertyName, n)
                exceptions.append(ex)

        if len(exceptions) > 0:
            raise PropertyService.MultipleExceptions(exceptions)

    def deleteAllProperties (self, curr = None):
        self.__properties.clear()
        return True

    def isPropertyDefined (self, theName, curr = None):
        if self.__properties.has_key(theName):
            return True
        else:
            return False

class PropertySetFactoryI (PropertyService.PropertySetFactory):

    def createPropertySet (self, curr):
        return PropertyService.PropertySetPrx.uncheckedCast(curr.adapter.addWithUUID(PropertySetI(None, None)))

    def createConstrainedPropertySet (self, allowedProperties, curr):
        return PropertyService.PropertySetPrx.uncheckedCast(curr.adapter.addWithUUID(PropertySetI(allowedProperties, None)))

    def createInitialPropertySet (self, initialProperties, curr):
        return PropertyService.PropertySetPrx.uncheckedCast(curr.adapter.addWithUUID(PropertySetI(None, initialProperties)))

class PropertyNamesIteratorI (PropertyService.PropertyNamesIterator):

    def __init__ (self, propertyNames):
        self.__propertyNames = propertyNames
        self.__index = 0

    def reset (self, curr = None):
        self.__index = 0
    
    def nextOne (self, curr = None):
        try:
            if self.__propertyNames[self.__index]:
                self.__index += 1
                return (True, self.__propertyNames[self.__index - 1])
        except IndexError:
            return (False, None)

    def nextN (self, howMany, curr = None):
        try:
            if self.__propertyNames[self.__index] and howMany > 0:
                self.__index += howMany
                return (True, self.__propertyNames[self.__index - howMany:min(self.__index, len(self.__propertyNames))])
        except IndexError:
            pass
        return (False, None)

    def destroy (self, curr):
        curr.adapter.remove(curr.id)

class PropertiesIteratorI (PropertyService.PropertiesIterator):

    def __init__ (self, properties):
        self.__properties = properties.items()
        self.__index = 0

    def reset (self, curr = None):
        self.__index = 0
    
    def nextOne (self, curr = None):
        try:
            if self.__properties[self.__index]:
                self.__index += 1
                return (True, self.__properties[self.__index - 1])
        except IndexError:
            return (False, None)

    def nextN (self, howMany, curr = None):
        try:
            if self.__properties[self.__index] and howMany > 0:
                self.__index += howMany
                return (True, self.__properties[self.__index - howMany:min(self.__index, len(self.__propertyNames))])
        except IndexError:
            pass
        return (False, None)

    def destroy (self, curr):
        curr.adapter.remove(curr.id)
